package com.zhanpple.color_picker.library

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import kotlin.math.roundToInt

/**
 * @author zhangmingping
 * @date 2022/2/22 11:04 上午
 * des:HSVColor
 */
class ColorProgressView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
    private val mPaint = Paint(Paint.ANTI_ALIAS_FLAG)
    private val mBgPaint = Paint(Paint.ANTI_ALIAS_FLAG)
    private val mBlackPath = Path()
    private val mWhitePath = Path()
    private val mPath = Path()


    private var mColor: Int = Color.RED
        set(value) {
            if (field != value) {
                field = value
                setColorShader()
            }
        }

    /**
     * 设置当前颜色
     */
    fun setCurrentColor(color: Int, useAlpha: Boolean = false, back: Boolean = true) {
        mColor = color
        if (useAlpha) {
            progress = Color.alpha(mColor) / 255F
        }
        invalidate()
        if (back) {
            invokeColorBack()
        }
    }


    private var countH = 0
    private var countV = 0
    private var colorWidth = 20
    private var progress = 1F
    private var progressOffset = 0F
    private var dexWidth = 0F

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        countH = measuredWidth / colorWidth + 1
        countV = measuredHeight / colorWidth + 1
        progressOffset = measuredHeight / 2F
        dexWidth = (measuredWidth - progressOffset * 2)
        setBgPath()
        setColorShader()
    }

    private fun setBgPath() {
        mBlackPath.reset()
        mWhitePath.reset()
        mPath.reset()
        mPath.addRoundRect(
            0F,
            0F,
            measuredWidth.toFloat(),
            measuredHeight.toFloat(),
            measuredHeight.toFloat(),
            measuredHeight.toFloat(),
            Path.Direction.CCW
        )
        repeat(countV) { v ->
            repeat(countH) { h ->
                var offset = 0F
                if (v % 2 == 0) {
                    offset = -colorWidth.toFloat()
                }
                if (h % 2 == 0) {
                    mWhitePath.addRect(
                        offset + colorWidth * h,
                        (v * colorWidth).toFloat(),
                        offset + colorWidth * (h + 1),
                        ((v + 1) * colorWidth).toFloat(),
                        Path.Direction.CCW
                    )
                } else {
                    mBlackPath.addRect(
                        offset + colorWidth * h,
                        (v * colorWidth).toFloat(),
                        offset + colorWidth * (h + 1),
                        ((v + 1) * colorWidth).toFloat(),
                        Path.Direction.CCW
                    )
                }
            }
        }
        mWhitePath.op(mPath, Path.Op.INTERSECT)
        mBlackPath.op(mPath, Path.Op.INTERSECT)
    }

    private fun setColorShader() {
        val r = Color.red(mColor)
        val g = Color.green(mColor)
        val b = Color.blue(mColor)
        val linearShader = LinearGradient(
            progressOffset,
            0F,
            dexWidth,
            0F,
            intArrayOf(Color.argb(0, r, g, b), Color.argb(255, r, g, b)),
            null,
            Shader.TileMode.CLAMP
        )

        mPaint.shader = linearShader
        postInvalidate()
    }


    @SuppressLint("ClickableViewAccessibility")
    override fun onTouchEvent(event: MotionEvent): Boolean {
        progress = ((event.x - progressOffset) / dexWidth).coerceAtMost(1F).coerceAtLeast(0F)
        invokeColorBack()
        invalidate()
        return true
    }

    private fun invokeColorBack() {
        val a = (progress * 255).roundToInt()
        val r = Color.red(mColor)
        val g = Color.green(mColor)
        val b = Color.blue(mColor)
        mColorBack?.invoke(Color.argb(a, r, g, b))
    }

    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)
        drawColorBg(canvas)
        drawColorProgress(canvas)
    }

    private fun drawColorProgress(canvas: Canvas?) {
        canvas?.let {
            mBgPaint.color = Color.BLACK
            it.drawCircle(
                progress * dexWidth + progressOffset,
                measuredHeight / 2F,
                measuredHeight * 0.9F / 2F,
                mBgPaint
            )
            mBgPaint.color = Color.WHITE
            it.drawCircle(
                progress * dexWidth + progressOffset,
                measuredHeight / 2F,
                measuredHeight * 0.7F / 2F,
                mBgPaint
            )
        }
    }

    private fun drawColorBg(canvas: Canvas?) {
        mBgPaint.color = Color.WHITE
        canvas?.drawPath(mWhitePath, mBgPaint)
        mBgPaint.color = Color.GRAY
        canvas?.drawPath(mBlackPath, mBgPaint)
        canvas?.drawPath(mPath, mPaint)
    }

    var mColorBack: ((Int) -> Unit)? = null

    init {
        setLayerType(LAYER_TYPE_SOFTWARE, null)
        mBgPaint.style = Paint.Style.FILL
        mPaint.style = Paint.Style.FILL
    }
}